package com.tca.common.learning.maven.custom.plugin;

import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @goal count
 */
public class CountMojo extends AbstractMojo {

    /**
     * 这里需要采用java1.4的编码规范, 注解需要加在注释里, 使用了@parameter注解后, 就可以在配置插件的时候进行配置
     * @Parameter
     */
    private String[] includes;

    private static final String[] DEFAULT_INCLUDES = {"java", "xml", "properties"};

    /**
     * @parameter expression="${project.basedir}"
     * @required
     * @readonly
     */
    private File basedir;

    /**
     * @parameter expression="${project.build.sourceDirectory}"
     * @required
     * @readonly
     */
    private File sourceDirectory;

    /**
     * @parameter expression="${project.build.testSourceDirectory}"
     * @required
     * @readonly
     */
    private File testSourceDirectory;

    /**
     * @parameter expression="${project.build.resources}"
     * @required
     * @readonly
     */
    private List<Resource> resources;

    /**
     * @parameter expression="${project.build.testResources}"
     * @required
     * @readonly
     */
    private List<Resource> testResources;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (includes == null || includes.length == 0) {
            includes = DEFAULT_INCLUDES;
        }
        try {
            // 源码
            countDir(sourceDirectory);
            // 测试代码
            countDir(testSourceDirectory);

            // 配置文件
            for (Resource resource : resources) {
                countDir(new File(resource.getDirectory()));
            }

            for (Resource testResource : testResources) {
                countDir(new File(testResource.getDirectory()));
            }
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to count lines of code", e);
        }


    }

    private void countDir(File file) throws Exception {
        if (!file.exists()) {
            return;
        }

        List<File> collected = new ArrayList<>();

        collectFiles(collected, file);

        int lines = 0;

        for (File sourceFile : collected) {
            lines += countLine(sourceFile);
        }

        String path = file.getAbsolutePath().substring(basedir.getAbsolutePath().length());

        getLog().info(path + ": " + lines + " lines of code in " + collected.size() + " files");
    }

    private int countLine(File file) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader(file));
        int lines = 0;

        try {
            while (reader.ready()) {
                reader.readLine();
                lines++;
            }
        } catch (Exception e) {

        } finally {
            reader.close();
        }

        return lines;
    }

    private void collectFiles(List<File> files, File file) {
        if (file.isFile()) {
            for (String include : includes) {
                if (file.getName().endsWith("." + include)) {
                    files.add(file);
                    break;
                }
            }
        } else {
            for (File sub : file.listFiles()) {
                collectFiles(files, sub);
            }
        }
    }
}
